<?php

namespace plugin\ycMassage\app\middleware;

use think\Request;
use think\Response;
use loong\oauth\facade\Auth;
use plugin\ycMassage\utils\Rsa;

/**
 * 根模块权限中间件
 * @author 贵州猿创科技有限公司
 * @Email 416716328@qq.com
 * @DateTime 2023-03-11
 */
class AccessMiddleware
{
    /**
     * 中间件入口
     * @author 贵州猿创科技有限公司
     * @Email 416716328@qq.com
     * @DateTime 2023-03-11
     */
    public function handle(Request $request, callable $handler): Response
    {
        # 跨域
        $this->allowCrossDomain();
        # 微信浏览器
        $this->isWehcatBrowser($request);
        $request->isWehcatBrowser = strpos($request->header('user-agent'), 'MicroMessenger') !== false;
        // 鉴权检测
        try {
            $this->canAccess($request);
            $response = $request->method() == 'OPTIONS' ? response('', 204) : $handler($request);
        } catch (\Throwable $th) {
            $response = json(['code' => $th->getCode(), 'msg' => $th->getMessage(), 'file' => $th->getFile()]);
        }
        return $response;
    }
    public function allowCrossDomain()
    {
        $customHeaders = [
            'Authorization',
            'Appid',
            'Area',
            'City',
            'Province',
            'Longitude',
            'Latitude',
            'Puid',
            'Icode',
            'Channelsid',
            'Dealeruid',
            'Content-Disposition'
        ];
        header('Access-Control-Allow-Origin:*');
        header('Access-Control-Allow-Credentials:true');
        header('Access-Control-Allow-Methods:GET, POST, PATCH, PUT, DELETE, OPTIONS');
        header('Access-Control-Allow-Headers:Origin, Content-Type, Cookie, X-CSRF-TOKEN, Accept, X-XSRF-TOKEN,' . implode(', ', $customHeaders));
        header('Access-Control-Expose-Headers:' . implode(', ', $customHeaders));
    }
    public function isWehcatBrowser($request)
    {
        $request->isWehcatBrowser = strpos($request->header('user-agent'), 'MicroMessenger') !== false;
    }

    /**
     * 业务逻辑
     * @author 贵州猿创科技有限公司
     * @Email 416716328@qq.com
     * @DateTime 2023-03-11
     */
    public function canAccess(Request $request): bool
    {
        # 无控制器地址
        if (!$request->control) {
            return true;
        }
        # 获取控制器鉴权信息
        $namespace = app()->getNamespace();
        $classNameSpace = "{$namespace}\\{$request->control}";
        $class = new \ReflectionClass($classNameSpace);
        $properties = $class->getDefaultProperties();
        # 无需登录方法
        $noNeedLogin = $properties['noNeedLogin'] ?? [];
        # 无需鉴权方法
        $noNeedAuth = $properties['noNeedAuth'] ?? [];
        # 无需验证APPID方法
        $noIdentifyApp = $properties['noNeedAppid'] ?? [];
        # 设置全局Appid
        $request->appid = $request->header('Appid');
        if (!in_array($request->action(), $noIdentifyApp)) {
            if (!$request->appid) {
                throw new \Exception('访问应用不存在', 404);
            }
        }
        # 是否强制登录
        $isForceLogin = true;
        if (in_array($request->action(), $noNeedLogin)) {
            $isForceLogin = false;
        }
        try {
            # 令牌验证
            $token = $request->header('Authorization');
            if (!$token) {
                throw new \Exception('请先登录', 12000);
            }
            $user = Auth::decrypt($token);
            if (!$user) {
                throw new \Exception('登录已过期，请重新登录', 12000);
            }
            $request->uid                = $user['id'];
            $request->saas_appid            = $user['saas_appid'];
            if ($request->appid != $request->saas_appid) {
                throw new \Exception('访问应用验证错误，请重新登录', 12000);
            }
        } catch (\Throwable $th) {
            if ($isForceLogin) {
                throw new \Exception($th->getMessage(), 12000);
            }
        }
        try {
            $Icode = $request->header('Icode');
            if ($Icode) {
                $request->puid = Rsa::decryptNumber($Icode);
            }
            if (!$request->puid) {
                $Puid = $request->header('Puid');
                if ($Puid) {
                    $request->puid = (int)$Puid;
                }
            }
        } catch (\Throwable $th) {
        }
        $DealerUid= $request->header('Dealeruid');
        if ($DealerUid) {
            $request->dealer_uid = (int)$DealerUid;
        }
        $area = $request->header('Area');
        $city = $request->header('City');
        $province = $request->header('Province');
        if ($area) {
            $request->area = (int)$area;
        } elseif ($city) {
            $request->city = (int)$city;
        } elseif ($province) {
            $request->province = (int)$province;
        }
        $Longitude = $request->header('Longitude');
        $Latitude = $request->header('Latitude');
        if ($Longitude && $Latitude) {
            $request->longitude = (float)$Longitude;
            $request->latitude = (float)$Latitude;
        }
        $Channelsid = $request->header('Channelsid');
        if ($Channelsid) {
            $request->channels_id = (int)$Channelsid;
        }
        # 不需要鉴权
        if (in_array($request->action(), $noNeedAuth)) {
            return true;
        }
        return true;
    }
}
